package com.annet.token.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.annet.token.model.ServerSetting;
import com.annet.token.repository.ServerSettingDao;
import com.annet.token.utils.AuthProperties;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.time.LocalTime;
import java.util.*;

/**
 * Copyright © 2016 深圳安泰创新科技股份有限公司 版权所有 All Right Reserved
 *
 * @author: Dingjb
 * 包名：com.annet.token.service
 * 时间：2020/12/31 15:35
 * 说明： 服务配置
 */
@Slf4j
@Service
public class ServerSettingServiceImpl {

    @Value("${spring.application.name}")
    private String applocationName;

    @Autowired(required = false) @Qualifier("serverSettingDao")
    private ServerSettingDao serverSettingDao;

    @Autowired(required = false) @Qualifier("authProperties")
    private AuthProperties authProperties;

    private String secret;
    //是否使用配置文件形式
    private boolean configFlag = false;

/*    @PostConstruct
    private void init() {
        ServerSetting serverSetting = ServerSetting.builder()
                .orgCode(LocalTime.now().toString())
                .name(applocationName).build();
        ServerSetting save = serverSettingDao.save(serverSetting);
        log.info("****ServerSetting={}", JSON.toJSON(save));
    }*/


    public String generateToken(JSONObject json) {
        String uname = json.getString("uname");
        String pwdMD5 = json.getString("pwd");
        String orgCode = json.getString("orgCode");
        Optional<ServerSetting> settingOptional = serverSettingDao.findByOrgCodeAndUnameAndPwd(orgCode, uname, pwdMD5);
        if (!settingOptional.isPresent()) {
            throw new RuntimeException("服务配置不存在");
        }
        setConfigFlag(false);
        ServerSetting setting = settingOptional.get();
        return createToken(setting.getUname(), setting.getPwd(), setting.getOrgCode(), setting.getSecretKey(), setting.getEnableIps(), setting.getUnableIps());
    }

    public String generateTokenByConfig(JSONObject json) {
        String uname = json.getString("uname");
        String pwdMD5 = json.getString("pwd");
        String orgCode = json.getString("orgCode");
        if (Objects.equals(uname, authProperties.getUNAME())
                && Objects.equals(pwdMD5, authProperties.getPwdMd5()) && Objects.equals(orgCode, authProperties.getOrgCode())) {
            setConfigFlag(true);
            return createToken(authProperties.getUNAME(), authProperties.getPwdMd5(), authProperties.getOrgCode(), authProperties.getSecretKey(), authProperties.getEnableIps(), authProperties.getUnableIps());
        }
        throw new RuntimeException("服务配置不存在");
    }

    public String createToken(String uname, String pwd, String orgCode, String secretKey, String enableIps, String unableIps) {

        Date iatDate = new Date();
        // expire time
        /**
         * token 过期时间: 7天
         */
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.DAY_OF_YEAR, 7);
        Date expiresDate = nowTime.getTime();

        // header Map
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        // build token
        // param backups {iss:Service, aud:APP}
        String token = null; // signature
        secretKey = Objects.isNull(secretKey) ? "B142F2A121E2F2B816D6D6DE5E4B3519" : secretKey;
        enableIps = Objects.isNull(enableIps) ? "" : enableIps;
        unableIps = Objects.isNull(unableIps) ? "" : unableIps;
        setSecret(secretKey);
        try {
            token = JWT.create()
                    .withHeader(map) // header
                    .withClaim("applocationName", applocationName)
                    .withClaim("uname", uname)
                    .withClaim("pwd", pwd)
                    .withClaim("orgCode", orgCode)
                    .withClaim("enableIps", enableIps)
                    .withClaim("unableIps", unableIps)
                    .withIssuedAt(iatDate) // sign time
                    .withExpiresAt(expiresDate) // expire time
                    .sign(Algorithm.HMAC256(secretKey));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return token;
    }

    public Boolean existsSetting(String orgCode, String uname, String pwd) {
        if (isConfigFlag()){
            return Objects.equals(uname, authProperties.getUNAME())
                    && Objects.equals(pwd, authProperties.getPwdMd5()) && Objects.equals(orgCode, authProperties.getOrgCode());
        }
        return serverSettingDao.existsByOrgCodeAndUnameAndPwd(orgCode, uname, pwd);
    }


    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public boolean isConfigFlag() {
        return configFlag;
    }

    public void setConfigFlag(boolean configFlag) {
        this.configFlag = configFlag;
    }
}
